#!/usr/bin/env python

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys

sys.path.append("/usr/share/vpntool")
import connections
import uiplatform
import password
import vpnc
import vpntool_rc

class VpnApplet(QWidget):
    
    """Tray applet for connecting, disconnecting and managing VPN connections"""
    
    def __init__(self):
        QWidget.__init__(self)
        
        # Dialog boxes
        self.connDlg = connections.Connections(self)
        self.passwordDlg = password.Password(self)
        
        # Menu
        self.menu = QMenu(self)
        self.connectAction = \
            self.addMenuAction("&Connect...", "icon:menu-connect.png", 
                               self.connect)
        self.disconnectAction = \
            self.addMenuAction("&Disconnect", "icon:menu-disconnect.png", 
                               self.disconnect)
        self.menu.addSeparator()
        self.showConnectionsAction = \
            self.addMenuAction("&Connections...", None, self.showConnections)
        self.menu.addSeparator()
        self.aboutAction = \
            self.addMenuAction("&About", "icon:menu-about.png", self.about)
        self.exitAction = \
            self.addMenuAction("&Quit", "icon:menu-quit.png", QApplication.exit)
        
        # Tray icon
        self.trayIcon = QSystemTrayIcon(self)
        self.trayIcon.setIcon(QIcon("icon:decrypted.png"))
        self.trayIcon.setContextMenu(self.menu)
        self.trayIcon.show()
        QObject.connect(self.trayIcon, 
            SIGNAL("activated(QSystemTrayIcon::ActivationReason)"), 
            self.onActivate)

        # VPNC manager and status timer
        self.vpncStatus = "disconnected"
        self.vpncTimer = QTimer()
        self.vpncTimer.setSingleShot(False)
        self.vpncTimer.setInterval(2000)
        QObject.connect(self.vpncTimer, SIGNAL("timeout()"), self.onTimeout)
        self.onTimeout()
        self.vpncTimer.start()        

    def addMenuAction(self, name, iconName, slot):
        """Create an action and add it to the menu"""
        if iconName and (uiplatform.name != "mac"):
            act = QAction(QIcon(iconName), self.tr(name), self)
        else:
            act = QAction(self.tr(name), self)
        self.menu.addAction(act)
        self.menu.connect(act, SIGNAL("triggered()"), slot)
        return act
    
    def about(self):
        about = QMessageBox(QMessageBox.Information, "About - vpntool",
            "Connect to Virtual Private Networks, " + 
            "manage connections.<br /><br />" + 
            "Version _VER_<br />" + 
            "Copyright &copy; 2008-2009 by Akos Polster<br />" +
            '<a href="http://code.google.com/p/vpntool/">vpntool Website</a>',
            QMessageBox.Close, self, 
            Qt.Dialog | Qt.MSWindowsFixedSizeDialogHint)
        about.setIconPixmap(QPixmap("icon:vpntool.png"))
        about.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
        about.setTextFormat(Qt.RichText)
        about.exec_()
    
    def showConnections(self):
        """Display connection list"""
        self.connDlg.exec_()
        self.updateMenu()
        
    def connect(self):
        """Connect to the default VPN"""
        conn = self.connDlg.connections[self.connDlg.defaultConn].copy()
        if not len(conn["userPassword"]):
            self.passwordDlg.labelUser.setText(conn["user"])
            self.passwordDlg.setWindowTitle("Connecting to %s - vpntool" % \
                                            conn["name"])
            ret = self.passwordDlg.exec_()
            if ret:
                conn["userPassword"] = self.passwordDlg.editUserPassword.text()
            else:
                return

        ret = vpnc.connect(conn)
        if ret:
            self.vpncStatus = "connected"
            self.showMessage("VPN connected", "Connected to %s" % conn["name"])
        else:
            self.vpncStatus = "disconnected"
            self.showMessage("Could not connect to VPN",
                             "Connection to %s has failed" % conn["name"])
        self.updateMenu()
    
    def disconnect(self):
        """Disconnect current VPN connection"""
        vpnc.disconnect()
        self.vpncStatus = "disconnected"
        self.showMessage("VPN disconnected", "")
        self.updateMenu()
        
    def updateMenu(self):
        """Enable/disable menu items depending on connection state"""
        self.disconnectAction.setEnabled(self.vpncStatus == "connected")
        self.connectAction.setEnabled((self.vpncStatus == "disconnected") and \
                                      (len(self.connDlg.connections) > 0))
        if self.vpncStatus == "connected":
            self.trayIcon.setIcon(QIcon("icon:encrypted.png"))
        else:
            self.trayIcon.setIcon(QIcon("icon:decrypted.png"))
        
    def onTimeout(self):
        """Handle timeout"""
        status = vpnc.getStatus()
        if (status == "connected") and (self.vpncStatus == "disconnected"):
            self.showMessage("VPN connected", "")
        elif (status == "disconnected") and (self.vpncStatus == "connected"):
            self.showMessage("VPN disconnected", "")
        self.vpncStatus = status
        self.updateMenu()

    def onActivate(self):
        """Tray icon has been activated"""
        if uiplatform.name == "maemo":
            # Work around menu not being shown on Maemo
            x = QCursor.pos().x()
            y = 60 
            self.menu.popup(QPoint(x, y))
        
    def showMessage(self, title, msg):
        """Show pop-up message"""
        if uiplatform.name == "mac":
            icon = QSystemTrayIcon.Information
        else:
            icon = QSystemTrayIcon.NoIcon
        self.trayIcon.showMessage(title, msg, icon)
        
        
if __name__ == "__main__":
    app = QApplication(sys.argv)
    app.setQuitOnLastWindowClosed(False)
    app.setOrganizationName("pipacs.com")
    app.setOrganizationDomain("pipacs.com")
    app.setApplicationName("vpntool")
    applet = VpnApplet()
    sys.exit(app.exec_())
